package com.example.dine.call.util;

import com.example.dine.call.entity.Queue;
import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * QRCodeUtils类，用于生成和解析二维码。
 */
public final class QRCodeUtils {

    /**
     * 保存二维码的文件夹路径。
     */
    private static final String QR_CODE_IMAGE_PATH = System.getProperty("user.home") + "/QRCode/";
    /**
     * 日期时间格式化器，用于格式化日期时间为字符串。
     */
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");

    static {
        // 确保保存二维码的文件夹是存在的
        File dir = new File(QR_CODE_IMAGE_PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    /**
     * 生成二维码并保存到指定路径。
     *
     * @param queue 包含排队信息的Queue对象。
     * @return 生成的二维码文件的路径。
     */
    public static String generate(Queue queue) {
        // 格式化创建时间为字符串
        String createdAt = queue.getCreatedAt().format(formatter);
        // 生成文件名
        String fileName = createdAt + "_" + queue.getTypeCode() + queue.getQueueNumber() + ".png";
        // 生成文件路径
        Path path = Paths.get(QR_CODE_IMAGE_PATH + fileName);
        try {
            // 设置二维码生成的提示信息
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            hints.put(EncodeHintType.MARGIN, 5);

            // 构建二维码内容字符串
            String queueInfo = "createdAt=" + createdAt + ",typeCode=" + queue.getTypeCode() + ",queueNumber=" + queue.getQueueNumber() + ",status=" + queue.getStatus() + ",partySize=" + queue.getPartySize();
            // 生成二维码矩阵
            BitMatrix matrix = new MultiFormatWriter().encode(queueInfo, BarcodeFormat.QR_CODE, 300, 300, hints);
            // 将二维码矩阵写入文件
            MatrixToImageWriter.writeToPath(matrix, "PNG", path);
            return path.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解析二维码文件并还原成Queue对象。
     *
     * @param filePath 二维码文件的路径。
     * @return 还原的Queue对象。
     */
    public static Queue parse(String filePath) {
        try {
            // 读取二维码图片文件
            BufferedImage bufferedImage = ImageIO.read(new File(filePath));
            // 创建亮度源
            LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
            // 创建二进制位图
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            // 创建二维码读取器
            MultiFormatReader reader = new MultiFormatReader();
            // 解码二维码
            Result result = reader.decode(bitmap);
            System.out.println("解析二维码内容: " + result.getText());

            // 解析二维码内容并还原成Queue对象
            String[] parts = result.getText().split(",");
            if (parts.length == 5) {
                // 解析创建时间
                String createdAt = parts[0].split("=")[1];
                // 解析餐桌类型代码
                String typeCode = parts[1].split("=")[1];
                // 解析排队序号
                int queueNumber = Integer.parseInt(parts[2].split("=")[1]);
                // 解析状态
                int status = Integer.parseInt(parts[3].split("=")[1]);
                // 解析就餐人数
                int partySize = Integer.parseInt(parts[4].split("=")[1]);

                // 创建Queue对象并设置属性
                Queue queue = new Queue();
                queue.setCreatedAt(LocalDateTime.parse(createdAt, formatter));
                queue.setTypeCode(typeCode);
                queue.setQueueNumber(queueNumber);
                queue.setStatus(status);
                queue.setPartySize(partySize);
                return queue;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
